package com.owlike.genson.ext.jsr353;
import java.io.StringWriter;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import javax.json.JsonArray;
import javax.json.JsonArrayBuilder;
import javax.json.JsonBuilderFactory;
import javax.json.JsonNumber;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.json.JsonString;
import javax.json.JsonValue;
import javax.json.JsonValue.ValueType;
import javax.json.spi.JsonProvider;
import com.owlike.genson.*;
import com.owlike.genson.ext.GensonBundle;
import com.owlike.genson.stream.JsonWriter;
import com.owlike.genson.stream.ObjectReader;
import com.owlike.genson.stream.ObjectWriter;
public class JSR353Bundle extends GensonBundle {
static final JsonBuilderFactory factory = JsonProvider.provider().createBuilderFactory(
new HashMap<String, String>());
@Override
public void configure(GensonBuilder builder) {
builder.withConverterFactory(new Factory<Converter<JsonValue>>() {
@Override
public Converter<JsonValue> create(Type type, Genson genson) {
return new JsonValueConverter();
}
});
}
public class JsonValueConverter implements Converter<JsonValue> {
@Override
public void serialize(JsonValue value, ObjectWriter writer, Context ctx) {
ValueType type = value.getValueType();
if (ValueType.STRING == type) writer.writeValue(((JsonString) value).getString());
else if (ValueType.ARRAY == type) writeArray((JsonArray) value, writer, ctx);
else if (ValueType.OBJECT == type) writeObject((JsonObject) value, writer, ctx);
else if (ValueType.NULL == type) writer.writeNull();
else if (ValueType.NUMBER == type) {
JsonNumber num = (JsonNumber) value;
if (num.isIntegral()) writer.writeValue(num.longValue());
else writer.writeValue(num.bigDecimalValue());
} else if (ValueType.FALSE == type) writer.writeValue(false);
else if (ValueType.TRUE == type) writer.writeValue(true);
else {
throw new IllegalStateException("Unknown ValueType " + type);
}
}
private void writeArray(JsonArray array, ObjectWriter writer, Context ctx) {
writer.beginArray();
for (JsonValue value : array)
serialize(value, writer, ctx);
writer.endArray();
}
private void writeObject(JsonObject object, ObjectWriter writer, Context ctx) {
writer.beginObject();
for (Entry<String, JsonValue> e : object.entrySet()) {
writer.writeName(e.getKey());
serialize(e.getValue(), writer, ctx);
}
writer.endObject();
}
@Override
public JsonValue deserialize(ObjectReader reader, Context ctx) {
com.owlike.genson.stream.ValueType type = reader.getValueType();
if (com.owlike.genson.stream.ValueType.OBJECT == type) {
return deserObject(reader, ctx);
} else if (com.owlike.genson.stream.ValueType.ARRAY == type) {
return deserArray(reader, ctx);
} else {
// let's allow using literal JsonValues outside of JsonArray or JsonObject
// thus we need this dummy builder to not by pass the creation mechanism
if (com.owlike.genson.stream.ValueType.STRING == type) {
return factory.createArrayBuilder().add(reader.valueAsString()).build().get(0);
} else if (com.owlike.genson.stream.ValueType.BOOLEAN == type) {
return reader.valueAsBoolean() ? JsonValue.TRUE : JsonValue.FALSE;
} else if (com.owlike.genson.stream.ValueType.NULL == type) {
return JsonValue.NULL;
} else if (com.owlike.genson.stream.ValueType.INTEGER == type) {
return factory.createArrayBuilder().add(reader.valueAsLong()).build().get(0);
} else if (com.owlike.genson.stream.ValueType.DOUBLE == type) {
return factory.createArrayBuilder().add(reader.valueAsDouble()).build().get(0);
}
}
throw new IllegalStateException("Unsupported ValueType " + type);
}
public JsonValue deserObject(ObjectReader reader, Context ctx) {
JsonObjectBuilder builder = factory.createObjectBuilder();
reader.beginObject();
while (reader.hasNext()) {
com.owlike.genson.stream.ValueType type = reader.next();
String name = reader.name();
if (com.owlike.genson.stream.ValueType.STRING == type) {
builder.add(name, reader.valueAsString());
} else if (com.owlike.genson.stream.ValueType.BOOLEAN == type) {
builder.add(name, reader.valueAsBoolean());
} else if (com.owlike.genson.stream.ValueType.NULL == type) {
builder.addNull(name);
} else if (com.owlike.genson.stream.ValueType.INTEGER == type) {
builder.add(name, reader.valueAsLong());
} else if (com.owlike.genson.stream.ValueType.DOUBLE == type) {
builder.add(name, reader.valueAsDouble());
} else builder.add(name, deserialize(reader, ctx));
}
reader.endObject();
return builder.build();
}
public JsonValue deserArray(ObjectReader reader, Context ctx) {
JsonArrayBuilder builder = factory.createArrayBuilder();
reader.beginArray();
while (reader.hasNext()) {
com.owlike.genson.stream.ValueType type = reader.next();
if (com.owlike.genson.stream.ValueType.STRING == type) {
builder.add(reader.valueAsString());
} else if (com.owlike.genson.stream.ValueType.BOOLEAN == type) {
builder.add(reader.valueAsBoolean());
} else if (com.owlike.genson.stream.ValueType.NULL == type) {
builder.addNull();
} else if (com.owlike.genson.stream.ValueType.INTEGER == type) {
builder.add(reader.valueAsLong());
} else if (com.owlike.genson.stream.ValueType.DOUBLE == type) {
builder.add(reader.valueAsDouble());
} else builder.add(deserialize(reader, ctx));
}
reader.endArray();
return builder.build();
}
}
static String toString(JsonValue value) {
StringWriter sw = new StringWriter();
com.owlike.genson.stream.JsonWriter writer = new JsonWriter(sw);
GensonJsonGenerator generator = new GensonJsonGenerator(writer);
generator.write(value);
generator.close();
return sw.toString();
}
static boolean toBoolean(Map<String, ?> config, String key) {
if (config == null) return false;
if (config.containsKey(key)) {
Object value = config.get(key);
if (value instanceof Boolean) {
return (Boolean) value;
} else if (value instanceof String) {
return Boolean.parseBoolean((String) value);
} else return false;
} else return false;
}
}